#ifndef __LS_BUFFER_H__
#define __LS_BUFFER_H__

#include <vector>
#include <iostream>
#include <cassert>

namespace log_system
{
    #define DEFAULT_BUFFER_SIZE (10 * 1024 * 1024)
    #define THRESHOLD_SIZE (80 * 1024 * 1024)
    #define LINEAR_INCREMENT_SIZE (10 * 1024 * 1024)
    class Buffer
    {
    public:
        Buffer():
            _buffer(DEFAULT_BUFFER_SIZE),
            _ridx(0),
            _widx(0)
        {}

        void push(const char* data, size_t len)
        {
            // 空间不足则扩容
            ensureEnoughSize(len);
            
            std::copy(data, data + len , &_buffer[_widx]);

            moveWriter(len);
        }
        size_t writableSize()
        {
            return _buffer.size() - _widx;
        }

        size_t readableSize()
        {
            return _widx - _ridx;
        }

        //返回可读数据的起始地址
        const char* data()
        {
            return &_buffer[_ridx];
        }
        
        void moveReader(size_t len)
        {
            assert(len <= readableSize());
            _ridx += len;
        }

        bool empty()
        {
            return _widx == _ridx;
        }

        void reset()
        {
            _widx = _ridx = 0;
        }

        //对Buffer实现交换操作
        void swap(Buffer& buffer)
        {
            _buffer.swap(buffer._buffer);
            std::swap(_ridx, buffer._ridx);
            std::swap(_widx, buffer._widx);
        }

    protected:
        void ensureEnoughSize(size_t writeSize)
        {
            if(writableSize() < writeSize)
            {
                size_t newSize = 0;
                do
                {
                    if(_buffer.size() < THRESHOLD_SIZE)
                    {
                        newSize = _buffer.size() * 2;
                    }
                    else
                    {
                        newSize = _buffer.size() + LINEAR_INCREMENT_SIZE;
                    }
                } while (newSize - _widx < writeSize);
                
                _buffer.resize(newSize);
            }
        }
        
        void moveWriter(size_t len)
        {
            assert(_widx + len <= _buffer.size());
            _widx += len;
        }

    private:
        std::vector<char> _buffer;
        size_t _ridx;
        size_t _widx;
    };
    
}


#endif